package com.stox.client.ui.javafx.chartingy.model.shape;

import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Group;

import com.stox.client.ui.javafx.chartingy.model.chart.Chart;
import com.stox.client.ui.javafx.core.util.CSS;
import com.stox.client.ui.javafx.core.util.UI;
import com.stox.shared.core.util.MathUtil;

public abstract class Shape extends Group {

	private final Chart<?, ?> chart;
	protected final DeletePoint deletePoint = new DeletePoint(this);

	public Shape(final Chart<?, ?> chart) {
		this.chart = chart;
		setManaged(false);
		UI.style(this, CSS.shape);
	}

	public abstract void update();

	public Chart<?, ?> getChart() {
		return chart;
	}
	
	public abstract ControlPoint[] getControlPoints();

	protected Point2D extrapolate(final ControlPoint start, final ControlPoint end, final Bounds bounds) {
		double y = 0;
		double x = 0;

		if (end.getCenterY() > start.getCenterY()) {
			if (end.getCenterX() > start.getCenterX()) {
				y = MathUtil.y(start.getCenterX(), start.getCenterY(), bounds.getMaxX(), bounds.getMaxY(), end.getCenterX());
				if (y > end.getCenterY()) {
					x = bounds.getMaxX();
					y = MathUtil.y(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY(), x);
				} else if (y < end.getCenterY()) {
					y = bounds.getMaxY();
					x = MathUtil.x(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY(), y);
				} else {
					x = bounds.getMaxX();
					y = bounds.getMaxY();
				}
			} else if (end.getCenterX() < start.getCenterX()) {
				y = MathUtil.y(start.getCenterX(), start.getCenterY(), bounds.getMinX(), bounds.getMaxY(), end.getCenterX());
				if (y > end.getCenterY()) {
					x = bounds.getMinX();
					y = MathUtil.y(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY(), x);
				} else if (y < end.getCenterY()) {
					y = bounds.getMaxY();
					x = MathUtil.x(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY(), y);
				} else {
					x = bounds.getMinX();
					y = bounds.getMaxY();
				}
			} else {
				x = start.getCenterX();
				y = bounds.getMaxY();
			}
		} else if (end.getCenterY() < start.getCenterY()) {
			if (end.getCenterX() > start.getCenterX()) {
				y = MathUtil.y(start.getCenterX(), start.getCenterY(), bounds.getMaxX(), bounds.getMinY(), end.getCenterX());
				if (y > end.getCenterY()) {
					y = bounds.getMinY();
					x = MathUtil.x(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY(), y);
				} else if (y < end.getCenterY()) {
					x = bounds.getMaxX();
					y = MathUtil.y(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY(), x);
				} else {
					x = bounds.getMaxX();
					y = bounds.getMinY();
				}
			} else if (end.getCenterX() < start.getCenterX()) {
				y = MathUtil.y(start.getCenterX(), start.getCenterY(), bounds.getMinX(), bounds.getMinY(), end.getCenterX());
				if (y > end.getCenterY()) {
					y = bounds.getMinY();
					x = MathUtil.x(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY(), y);
				} else if (y < end.getCenterY()) {
					x = bounds.getMinX();
					y = MathUtil.y(start.getCenterX(), start.getCenterY(), end.getCenterX(), end.getCenterY(), x);
				} else {
					x = bounds.getMinX();
					y = bounds.getMinY();
				}
			} else {
				x = start.getCenterX();
				y = bounds.getMaxY();
			}
		} else {
			y = start.getCenterY();
			if (end.getCenterX() > start.getCenterX()) {
				x = bounds.getMaxX();
			} else if (end.getCenterX() < start.getCenterX()) {
				x = bounds.getMinX();
			} else {
				x = start.getCenterX();
			}
		}
		return new Point2D(x, y);
	}

}
